/*
 * DynamicArithmeticCompresor.cpp
 *
 *  Created on: 27/11/2009
 *      Author: ngonzalez
 */

#include "DynamicArithmeticCompresor.h"


DynamicArithmeticCompresor::DynamicArithmeticCompresor() {

	this->contextTable = new ContextTable(256);
	this->bitManager = new BitManager();
}

DynamicArithmeticCompresor::~DynamicArithmeticCompresor() {

	delete this->contextTable;
	delete this->bitManager;

}

string DynamicArithmeticCompresor::doCompress(){

	int counter = 0;
	string stringToCompress = this->getStringToCompress();
	int stringSize = stringToCompress.size();
	int askii;

	char theChar;
	char context;
	string nullChar = "e";

	this->setFloor(0);

    unsigned int max = (predefinedMaxRoof);
    this->setRoof(max);

    while (counter < stringSize) {

		theChar = stringToCompress[counter];

		context = counter != 0 ? stringToCompress[counter-1] : nullChar[0];

		askii = static_cast<int>(theChar);

		double acumulatedProbability;

		unsigned long int vecLength = CompresorUtil::calculateLength(this->getFloor(),this->getRoof());

		acumulatedProbability = this->getContextTable()->getAcummulatedProbability(context,static_cast<char>(askii-1));

		unsigned int  pisoAux = ceil( CompresorUtil::calculateNewRoof(acumulatedProbability,vecLength,this->getFloor()));

		acumulatedProbability = this->getContextTable()->getAcummulatedProbability(context,static_cast<char>(askii));

		this->setRoof( floor(CompresorUtil::calculateNewRoof(acumulatedProbability,vecLength,this->getFloor())) );
		
		this->setFloor(pisoAux+1);

		this->getContextTable()->updateTable(context,theChar);

		this->getBitManager()->setFloor(this->getFloor());

		this->getBitManager()->setRoof(this->getRoof());

		//cout<<"piso "<<this->theFloor<<endl;
		//cout<<" techo"<<theRoof<<endl;

		if (counter < stringSize-1) {

			this->getBitManager()->normalize();

			this->setFloor(this->getBitManager()->getNormalizedFloor());

			this->setRoof(this->getBitManager()->getNormalizedRoof());
		}

	    counter++;
	}

	unsigned int i;
	unsigned char caracter;
	cout << endl;

	this->getBitManager()->setRoof(this->getFloor());

	string compresedString = this->getBitManager()->getCompressedString();

	for (i = 0 ; i < compresedString.size() ; i++) {
		caracter = compresedString[i];
		bitset<8> byte(caracter);
	}

	return compresedString;
}


/*----------------------------Getter & Setters---------------------------------*/


ContextTable* DynamicArithmeticCompresor::getContextTable() const {
	return this->contextTable;
}


BitManager *DynamicArithmeticCompresor::getBitManager() const {
	return bitManager;
}


unsigned int DynamicArithmeticCompresor::getFloor() const {
	return theFloor;
}

unsigned int DynamicArithmeticCompresor::getRoof() const {
	return theRoof;
}

void DynamicArithmeticCompresor::setFloor(unsigned int floor) {
	this->theFloor = floor;
}

void DynamicArithmeticCompresor::setRoof(unsigned int roof) {
	this->theRoof = roof;
}

string DynamicArithmeticCompresor::getStringToCompress() const {
	return stringToCompress;
}

void DynamicArithmeticCompresor::setStringToCompress(string stringToCompress) {
	this->stringToCompress = stringToCompress;
}

/*--------------------------End Getter & Setters-------------------------------*/
